package com.chushouya.manager.service.admin.impl;

import com.general.framework.core.lang.*;
import com.chushouya.common.constant.RoleKeyDefined;
import com.chushouya.common.support.Contexts;
import com.chushouya.manager.dao.entity.RoleEntity;
import com.chushouya.manager.dao.entity.RoleMenuEntity;
import com.chushouya.manager.dao.entity.UserRoleEntity;
import com.chushouya.manager.dao.repository.RoleMenuRepository;
import com.chushouya.manager.dao.repository.RoleRepository;
import com.chushouya.manager.dao.repository.UserRoleRepository;
import com.chushouya.manager.dto.admin.role.RoleListDTO;
import com.chushouya.manager.dto.admin.role.RoleQuery;
import com.chushouya.manager.dto.admin.role.RoleSaveDTO;
import com.chushouya.manager.dto.admin.role.RoleSelectDTO;
import com.chushouya.manager.service.admin.RoleService;
import com.google.common.collect.Maps;
import com.general.framework.core.enums.DelFlagEnum;
import com.general.framework.core.enums.StatusEnum;
import com.general.framework.core.exception.Ex;
import com.general.framework.core.schema.PageResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

@Service
@Slf4j
public class RoleServiceImpl implements RoleService {

    @Resource
    private RoleRepository roleRepository;

    @Resource
    private UserRoleRepository userRoleRepository;

    @Resource
    private RoleMenuRepository roleMenuRepository;



    private Map<String, String> getSystemInitRole() {
        // 初始化超级管理员角色和商家角色
        Map<String, String> roleInitMap = Maps.newHashMap();
        roleInitMap.put(RoleKeyDefined.admin, "超级管理员角色");
        roleInitMap.put(RoleKeyDefined.merchant, "商家角色");
        return roleInitMap;
    }

    @PostConstruct
    public void init() {

        for (String roleKey : this.getSystemInitRole().keySet()){
            RoleQuery query = new RoleQuery();
            query.setRoleKey(roleKey);
            RoleEntity roleEntity = roleRepository.selectOneRole(query);
            if (Objects.isNull(roleEntity)) {
                final String roleName = this.getSystemInitRole().get(roleKey);
                log.info("===== CAN NOT FIND ROLE:{} {}, SYSTEM BEGIN INIT =====", roleKey, roleName);
                roleEntity = new RoleEntity();
                roleEntity.setRoleName(roleName);
                roleEntity.setRoleKey(roleKey);
                roleEntity.setRoleSort(Numbers.INTEGER_ZERO);
                roleEntity.setDataScope(Numbers.INTEGER_ONE.toString());
                roleEntity.setMenuCheckStrictly(Boolean.TRUE);
                roleEntity.setStatus(StatusEnum.normal.value());
                final Date timeNow = Dates.getTimeNow();
                roleEntity.setCreateTime(timeNow);
                roleEntity.setUpdateTime(timeNow);
                roleEntity.setCreateBy("平台系统");
                roleEntity.setUpdateBy("平台系统");
                roleEntity.setRemark("系统内置角色");
                roleRepository.insertSelective(roleEntity);
            }
        }

    }

    @Override
    public PageResult<RoleListDTO> selectRolePageResult(RoleQuery query) {
        PageResult<RoleEntity> pageResult = roleRepository.selectRolePageResult(query);
        if (Lists.isEmpty(pageResult.getRows())) {
            return PageResult.empty();
        }
        List<RoleListDTO> roleList = Lists.newArrayList();
        final Map<String, String> systemInitRole = this.getSystemInitRole();
        pageResult.getRows().forEach(item->{
            RoleListDTO role = Beans.copy(item, RoleListDTO.class);
            role.setSystemInit(systemInitRole.containsKey(item.getRoleKey()));
            roleList.add(role);
        });
        return new PageResult<>(roleList, pageResult.getTotal());
    }

    @Override
    public List<RoleListDTO> selectRoleList(RoleQuery query) {
        List<RoleEntity> roleList = roleRepository.selectRoleList(query);
        return Beans.copyList(roleList, RoleListDTO.class);
    }

    @Override
    public Set<String> selectRolePermission(Long adminUserId) {
        String regex = ",";
        // 用户分配的角色
        List<UserRoleEntity> userRoleList = userRoleRepository.selectUserRole(adminUserId);
        Set<Long> roleIdList = userRoleList.stream().map(UserRoleEntity::getRoleId).collect(Collectors.toSet());

        List<RoleEntity> roleList = roleRepository.selectByRoleIdList(new ArrayList<>(roleIdList));
        Set<String> permsSet = new HashSet<>();
        for (RoleEntity role : roleList) {
            permsSet.addAll(Arrays.asList(role.getRoleKey().trim().split(regex)));
        }
        return permsSet;
    }

    private boolean checkRoleNameUnique(RoleSaveDTO role) {
        RoleQuery query = new RoleQuery();
        query.setRoleName(role.getRoleName());
        if (Longs.notNullAndZero(role.getRoleId())) {
            query.setIdNotEqualTo(role.getRoleId());
        }
        RoleEntity roleEntity = roleRepository.selectOneRole(query);
        return Objects.nonNull(roleEntity);
    }

    private boolean checkRoleKeyUnique(RoleSaveDTO role) {
        RoleQuery query = new RoleQuery();
        query.setRoleKey(role.getRoleKey());
        if (Longs.notNullAndZero(role.getRoleId())) {
            query.setIdNotEqualTo(role.getRoleId());
        }
        RoleEntity roleEntity = roleRepository.selectOneRole(query);
        return Objects.nonNull(roleEntity);
    }

    @Override
    public RoleSaveDTO getRoleDetail(Long roleId) {
        RoleEntity roleEntity = roleRepository.selectByPrimaryKey(roleId);
        if (Objects.isNull(roleEntity)) {
            throw Ex.business("角色{}不存在", roleId);
        }
        RoleSaveDTO roleDTO = Beans.copy(roleEntity, RoleSaveDTO.class);
        List<RoleMenuEntity> roleMenuEntityList = roleMenuRepository.selectRoleMenuByRoleIdList(Lists.asList(roleId));
        if (Lists.isNotEmpty(roleMenuEntityList)) {
            roleDTO.setMenuIdList(roleMenuEntityList.stream().map(RoleMenuEntity::getMenuId).collect(Collectors.toList()));
        }
        return roleDTO;
    }

    @Override
    public void updateRoleStatus(Long roleId, Integer status) {
        RoleEntity update = new RoleEntity();
        update.setRoleId(roleId);
        update.setStatus(status);
        update.setUpdateTime(Dates.getTimeNow());
        update.setUpdateBy(Contexts.getUserContext().getUserName());
        roleRepository.updateByPrimaryKeySelective(update);
    }

    @Override
    public void deleteRole(Long roleId) {
        RoleEntity update = new RoleEntity();
        update.setRoleId(roleId);
        update.setUpdateTime(Dates.getTimeNow());
        update.setDelFlag(DelFlagEnum.delete.getValue());
        update.setUpdateBy(Contexts.getUserContext().getUserName());
        roleRepository.updateByPrimaryKeySelective(update);
        //删掉角色对应的用户角色关系
        roleMenuRepository.deleteByRoleId(roleId);
    }

    @Override
    public List<RoleSelectDTO> selectRoleSelect() {
        List<RoleEntity> roleList = roleRepository.selectRoleList(new RoleQuery());
        return Beans.copyList(roleList, RoleSelectDTO.class);
    }

    @Override
    public void deleteAuthUser(Long roleId, List<Long> adminUserIdList) {
        userRoleRepository.deleteUserRole(roleId, adminUserIdList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertAuthUser(Long roleId, List<Long> adminUserIdList) {
        if (Lists.isNotEmpty(adminUserIdList)) {
            adminUserIdList.forEach(userId -> {
                UserRoleEntity userRole = new UserRoleEntity();
                userRole.setRoleId(roleId);
                userRole.setAdminUserId(userId);
                userRoleRepository.insertSelective(userRole);
            });
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long addRole(RoleSaveDTO role) {
        if (this.checkRoleNameUnique(role)) {
            throw Ex.business("新增角色'{}'失败，角色名称已存在", role.getRoleName());
        }
        if (this.checkRoleKeyUnique(role)) {
            throw Ex.business("新增角色'{}'失败，角色权限已存在", role.getRoleName());
        }
        RoleEntity roleEntity = Beans.copy(role, RoleEntity.class);
        roleEntity.setCreateTime(Dates.getTimeNow());
        roleEntity.setCreateBy(Contexts.getUserContext().getUserName());
        roleRepository.insertSelective(roleEntity);
        this.saveRoleMenu(roleEntity.getRoleId(), role.getMenuIdList(), Boolean.FALSE);
        return roleEntity.getRoleId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long editRole(RoleSaveDTO role) {
        Check.notNull(role.getRoleId(), "roleId can not be null");
        if (this.checkRoleNameUnique(role)) {
            throw Ex.business("修改角色'{}'失败，角色名称已存在", role.getRoleName());
        } else if (this.checkRoleKeyUnique(role)) {
            throw Ex.business("修改角色'{}'失败，角色权限已存在", role.getRoleName());
        }
        RoleEntity roleEntity = Beans.copy(role, RoleEntity.class);
        roleEntity.setUpdateTime(Dates.getTimeNow());
        roleEntity.setUpdateBy(Contexts.getUserContext().getUserName());
        roleRepository.updateByPrimaryKeySelective(roleEntity);
        this.saveRoleMenu(roleEntity.getRoleId(), role.getMenuIdList(), Boolean.TRUE);
        return roleEntity.getRoleId();
    }
    private void saveRoleMenu(Long roleId, List<Long> menuIdList, boolean editMode){
        if (editMode) {
            roleMenuRepository.deleteByRoleId(roleId);
        }
        if (Lists.isNotEmpty(menuIdList)) {
            List<RoleMenuEntity> roleMenuList = new ArrayList<>();
            menuIdList.forEach(menuId -> {
                RoleMenuEntity roleMenu = new RoleMenuEntity();
                roleMenu.setRoleId(roleId);
                roleMenu.setMenuId(menuId);
                roleMenuList.add(roleMenu);
            });
            roleMenuRepository.insertList(roleMenuList);
        }
    }

}
